/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// A wrapper around Scaleform's GSysAllocBase interface to delegate memory allocations to CryMemoryManager
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef _GALLOCATOR_CRYMEM_H_
#define _GALLOCATOR_CRYMEM_H_

#pragma once


#ifndef EXCLUDE_SCALEFORM_SDK


#pragma warning(push)
#pragma warning(disable : 6326) // Potential comparison of a constant with another constant
#pragma warning(disable : 6011) // Dereferencing NULL pointer
#include <GSysAlloc.h>
#pragma warning(pop)


class GFxTempMemoryArenaWrapper : public GSysAllocPaged
{
public:
	// GSysAllocPaged interface
	virtual void GetInfo(Info* i) const;
	virtual void* Alloc(UPInt size, UPInt align);
	virtual bool Free(void* ptr, UPInt size, UPInt align);

public:
	GFxTempMemoryArenaWrapper();
	~GFxTempMemoryArenaWrapper();

public:
	bool IsActive() const { return m_tempArenaActive; }

	int Create();
	void Destroy();

public:
	void SetAlloc(GSysAllocPaged* pAlloc);

public:
	static void InitCVars();

private:
	static int ms_sys_flash_use_temp_arena;

private:
	CryCriticalSection m_lock;
	GSysAllocPaged* m_pAlloc;
	bool m_tempArenaActive;
};


struct CryGFxMemInterface
{
public:
	struct Stats
	{
		uint32 AllocCount;
		uint32 FreeCount;
		size_t Allocated;
	};

public:
	virtual Stats GetStats() const = 0;
	virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0;
	virtual GSysAllocBase* GetSysAllocImpl() = 0;
	virtual GFxTempMemoryArenaWrapper& GetTempMemoryArena() = 0;

	virtual ~CryGFxMemInterface() {}
};



















class GSysAllocCryMem : public GSysAllocPaged, public CryGFxMemInterface
{
public:
	// GSysAllocPaged interface
	virtual void GetInfo(Info* i) const;
	virtual void* Alloc(UPInt size, UPInt align);
	virtual bool Free(void* ptr, UPInt size, UPInt align);

public:
	// CryGFxMemInterface interface
	virtual Stats GetStats() const;
	virtual void GetMemoryUsage(ICrySizer* pSizer) const;
	virtual GSysAllocBase* GetSysAllocImpl();
	virtual GFxTempMemoryArenaWrapper& GetTempMemoryArena();

public:
	explicit GSysAllocCryMem(size_t addressSpaceSize);
	virtual ~GSysAllocCryMem();

private:
	enum
	{
		MinGranularity = 64 * 1024, // No larger than a page on PS3 - try and keep all platforms equivalent
	};

private:
	IPageMappingHeap* m_pHeap;
	Stats m_stats;




	GFxTempMemoryArenaWrapper m_tempArena;
};


class GSysAllocStaticCryMem : public CryGFxMemInterface
{
public:
	// CryGFxMemInterface interface
	virtual Stats GetStats() const;
	virtual void GetMemoryUsage(ICrySizer* pSizer) const;
	virtual GSysAllocBase* GetSysAllocImpl();
	virtual GFxTempMemoryArenaWrapper& GetTempMemoryArena();

public:
	GSysAllocStaticCryMem(size_t poolSize);
	virtual ~GSysAllocStaticCryMem();

	bool IsValid() const { return m_pStaticAlloc && m_pMem; }

private:
	GSysAllocStatic* m_pStaticAlloc;
	void* m_pMem;
	size_t m_size;
	GFxTempMemoryArenaWrapper m_tempArena;
};


#endif // #ifndef EXCLUDE_SCALEFORM_SDK


#endif // #ifndef _GALLOCATOR_CRYMEM_H_